﻿using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using ScrumFactory.Data;
using ScrumFactory.Services.Logic;
using System.Linq;

namespace ScrumFactory.Services.Logic.Tests {
    
    [TestClass()]
    public class BacklogServiceTest {

        [TestMethod()]
        public void GetsBacklog() {
            var repository = new Mock<IBacklogRepository>();

            var items = new List<BacklogItem>();

            repository.Setup(r => r.GetCurrentBacklog("project1")).Returns(items).Verifiable("GetBacklog was not invoked");

            var target = new BacklogService(repository.Object, null);

            var result = target.GetCurrentBacklog("project1");

            Assert.AreSame(items, result, "Result does not match expectation");
        }

        [TestMethod]
        public void GetLeftHoursByDay() {

            Project project = CreateProject1();
            project.Sprints = CreateSprints();
            List<BacklogItem> items = CreateItems();

            /*-----------------------------------------------------------
             *          plan 0  plan 1  plan 2    plan 3
             *          1/1     1/1 10/1  16/1  31/1  2/2  14/2       
             * item A   30      12  12    20    2     2    0
             * item B   40      2   0     0     0     0    0
             * item C   33      24  24    24    24    0    0
             * 
             * total    103     38  36    44    26    2    0
             * 
             *----------------------------------------------------------*/

            var backlogRepository = new Mock<IBacklogRepository>();
            backlogRepository.Setup(r => r.GetBacklog("project1")).Returns(items);

            var projectsService = new Mock<IProjectsService>();
            projectsService.Setup(r => r.GetProject("project1")).Returns(project);

            var target = new BacklogService(backlogRepository.Object, projectsService.Object);

            List<BurndownLeftHoursByDay> result = (List<BurndownLeftHoursByDay>)target.GetBurndownHoursByDay("project1");

            Assert.IsTrue(result.Where(h => h.LeftHoursMetric == LeftHoursMetrics.LEFT_HOURS).ToArray().Length == 6, "Some burndow days were missing.");
            
            Assert.IsTrue(result[0].Date.Equals(new System.DateTime(2010, 1, 1)), "Burndown day 1 is wrong.");
            Assert.IsTrue(result[0].TotalHours==38, "Burndown day 1 hours is wrong.");

            Assert.IsTrue(result[1].Date.Equals(new System.DateTime(2010, 1, 10)), "Burndown day 2 is wrong.");
            Assert.IsTrue(result[1].TotalHours == 36, "Burndown day 2 hours is wrong.");

            Assert.IsTrue(result[2].Date.Equals(new System.DateTime(2010, 1, 16)), "Burndown day 3 is wrong.");
            Assert.IsTrue(result[2].TotalHours == 44, "Burndown day 3 hours is wrong.");
            
            Assert.IsTrue(result[3].Date.Equals(new System.DateTime(2010, 1, 31)), "Burndown day 5 is wrong.");
            Assert.IsTrue(result[3].TotalHours == 26, "Burndown day 5 hours is wrong.");

            Assert.IsTrue(result[4].Date.Equals(new System.DateTime(2010, 2, 2)), "Burndown day 6 is wrong.");
            Assert.IsTrue(result[4].TotalHours == 2, "Burndown day 6 hours is wrong.");

            Assert.IsTrue(result[5].Date.Equals(new System.DateTime(2010, 2, 14)), "Burndown day 7 is wrong.");
            Assert.IsTrue(result[5].TotalHours == 0, "Burndown day 7 hours is wrong.");
            
        }



        private Project CreateProject1() {
            return new Project() { ProjectUId = "project1", Status = (short)ProjectStatus.PROJECT_STARTED };
        }

        private List<Sprint> CreateSprints() {
            return new List<Sprint>() {
                new Sprint() { SprintNumber=1, StartDate = new System.DateTime(2010, 1, 1), EndDate = new System.DateTime(2010,1, 15) },
                new Sprint() { SprintNumber=2, StartDate = new System.DateTime(2010, 1, 16), EndDate = new System.DateTime(2010,1, 30) },
                new Sprint() { SprintNumber=3, StartDate = new System.DateTime(2010, 1, 31), EndDate = new System.DateTime(2010,2, 15) }
            };
        }

        private List<BacklogItem> CreateItems() {
            List < BacklogItem >  items = new List<BacklogItem>() {
                new BacklogItem() { BacklogItemUId="ITEM A", CreateDate = new System.DateTime(2010,1,1), FinishedAt= new System.DateTime(2010,2,14) },
                new BacklogItem() { BacklogItemUId="ITEM B", CreateDate = new System.DateTime(2010,1,1), FinishedAt= new System.DateTime(2010,1,10) },
                new BacklogItem() { BacklogItemUId="ITEM C", CreateDate = new System.DateTime(2010,1,17), FinishedAt= new System.DateTime(2010,2,2) }            
            };

            items.Single(i => i.BacklogItemUId == "ITEM A").PlannedHours = new List<PlannedHour>() {
                new PlannedHour() { Hours = 30, PlanningNumber=0, SprintNumber=1 },
                new PlannedHour() { Hours = 12, PlanningNumber=1, SprintNumber=1 },
                new PlannedHour() { Hours = 20, PlanningNumber=2, SprintNumber=2 },
                new PlannedHour() { Hours = 2, PlanningNumber=3, SprintNumber=3 }
            };

            items.Single(i => i.BacklogItemUId == "ITEM B").PlannedHours = new List<PlannedHour>() {
                new PlannedHour() { Hours = 40, PlanningNumber=0, SprintNumber=1 },
                new PlannedHour() { Hours = 2, PlanningNumber=1, SprintNumber=1 }
            };

            items.Single(i => i.BacklogItemUId == "ITEM C").PlannedHours = new List<PlannedHour>() {
                new PlannedHour() { Hours = 33, PlanningNumber=0, SprintNumber=2 },
                new PlannedHour() { Hours = 24, PlanningNumber=1, SprintNumber=3 }
            };

            return items;
        }
    }
}
